Return an appropriate GtkStyle from gtk_rc_get_style_by_paths()
authorOwen W. Taylor <otaylor@fishsoup.net>
Mon, 20 Dec 2010 18:48:44 +0000 (13:48 -0500)
committerOwen W. Taylor <otaylor@fishsoup.net>
Tue, 21 Dec 2010 19:27:25 +0000 (14:27 -0500)
Always returning NULL (no match) from gtk_rc_get_style_by_paths()
means that looking up colors and style properties based on the
GtkStyle will give default values instead of themed values. We can
do better by returning a GtkStyle based on a GtkWidgetPath that we
figure out from the values passed in to get_style_by_paths().

https://bugzilla.gnome.org/show_bug.cgi?id=637520

gtk/gtkrc.c
gtk/gtkstyle.c
gtk/gtkstyle.h

index 44b03714791e5fc938dc8a5a1ee05929d1b9d60e..b0d99c8d39995fa6bf93249ba6516e1fddd807f3 100644 (file)
@@ -807,7 +807,83 @@ gtk_rc_get_style_by_paths (GtkSettings *settings,
                           const char  *class_path,
                           GType        type)
 {
-  return NULL;
+  GtkWidgetPath *path;
+  GtkStyle *style;
+
+  path = gtk_widget_path_new ();
+
+  /* For compatibility, we return a GtkStyle based on a GtkStyleContext
+   * with a GtkWidgetPath appropriate for the supplied information.
+   *
+   * GtkWidgetPath is composed of a list of GTypes with optional names;
+   * In GTK+-2.0, widget_path consisted of the widget names, or
+   * the class names for unnamed widgets, while class_path had the
+   * class names always. So, use class_path to determine the GTypes
+   * and extract widget names from widget_path as applicable.
+   */
+  if (class_path == NULL)
+    {
+      gtk_widget_path_append_type (path, type == G_TYPE_NONE ? GTK_TYPE_WIDGET : type);
+    }
+  else
+    {
+      const gchar *widget_p, *widget_next;
+      const gchar *class_p, *class_next;
+
+      widget_next = widget_path;
+      class_next = class_path;
+
+      while (*class_next)
+       {
+         GType component_type;
+         gchar *component_class;
+         gchar *component_name;
+         gint pos;
+
+         class_p = class_next;
+         if (*class_p == '.')
+           class_p++;
+
+         widget_p = widget_next; /* Might be NULL */
+         if (widget_p && *widget_p == '.')
+           widget_p++;
+
+         class_next = strchr (class_p, '.');
+         if (class_next == NULL)
+           class_next = class_p + strlen (class_p);
+
+         if (widget_p)
+           {
+             widget_next = strchr (widget_p, '.');
+             if (widget_next == NULL)
+               widget_next = widget_p + strlen (widget_p);
+           }
+
+         component_class = g_strndup (class_p, class_next - class_p);
+         if (widget_p && *widget_p)
+           component_name = g_strndup (widget_p, widget_next - widget_p);
+         else
+           component_name = NULL;
+
+         component_type = g_type_from_name (component_class);
+         if (component_type == G_TYPE_INVALID)
+           component_type = GTK_TYPE_WIDGET;
+
+         pos = gtk_widget_path_append_type (path, component_type);
+         if (component_name != NULL && strcmp (component_name, component_name) != 0)
+           gtk_widget_path_iter_set_name (path, pos, component_name);
+
+         g_free (component_class);
+         g_free (component_name);
+       }
+    }
+
+  style = _gtk_style_new_for_path (_gtk_settings_get_screen (settings),
+                                  path);
+
+  gtk_widget_path_free (path);
+
+  return style;
 }
 
 /**
index e02beb5655749893ebfb4196b0346d5e68e7537f..3bfc66422a0e0dd5af75db6a468746158e67cb1e 100644 (file)
@@ -798,6 +798,26 @@ gtk_style_copy (GtkStyle *style)
   return new_style;
 }
 
+GtkStyle*
+_gtk_style_new_for_path (GdkScreen     *screen,
+                        GtkWidgetPath *path)
+{
+  GtkStyleContext *context;
+  GtkStyle *style;
+
+  context = gtk_style_context_new ();
+  gtk_style_context_set_screen (context, screen);
+  gtk_style_context_set_path (context, path);
+
+  style = g_object_new (GTK_TYPE_STYLE,
+                        "context", context,
+                        NULL);
+
+  g_object_unref (context);
+
+  return style;
+}
+
 /**
  * gtk_style_new:
  * @returns: a new #GtkStyle.
@@ -809,22 +829,15 @@ gtk_style_copy (GtkStyle *style)
 GtkStyle*
 gtk_style_new (void)
 {
-  GtkStyleContext *context;
   GtkWidgetPath *path;
   GtkStyle *style;
 
-  context = gtk_style_context_new ();
-  gtk_style_context_set_screen (context, gdk_screen_get_default ());
-
   path = gtk_widget_path_new ();
   gtk_widget_path_append_type (path, GTK_TYPE_WIDGET);
-  gtk_style_context_set_path (context, path);
 
-  style = g_object_new (GTK_TYPE_STYLE,
-                        "context", context,
-                        NULL);
+  style = _gtk_style_new_for_path (gdk_screen_get_default (),
+                                  path);
 
-  g_object_unref (context);
   gtk_widget_path_free (path);
 
   return style;
index efd78a7cfc1751a989f0305fd7056e2d04cd6a5e..7aec22d88e577d9117d169ecfaa906f9cad482ec 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <gdk/gdk.h>
 #include <gtk/gtkenums.h>
+#include <gtk/gtkwidgetpath.h>
 
 
 G_BEGIN_DECLS
@@ -634,10 +635,13 @@ void gtk_style_get                (GtkStyle    *style,
 #endif
 
 /* --- private API --- */
+GtkStyle*     _gtk_style_new_for_path        (GdkScreen          *screen,
+                                             GtkWidgetPath      *path);
 void          _gtk_style_shade               (const GdkColor     *a,
                                               GdkColor           *b,
                                               gdouble             k);
 
+
 void   gtk_draw_insertion_cursor    (GtkWidget          *widget,
                                      cairo_t            *cr,
                                      const GdkRectangle *location,